perm filename EDIT2.DOC[P,JRA] blob
sn#203336 filedate 1976-02-23 generic text, type T, neo UTF8
A User's Guide to ED110
Lyle Ramshaw
March, 1974
Revision by Forrest Howard, June, 1975
INTRODUCTION
ED110 is and in-core editor for the Harvard instructional Lisp
system L110. It allows the user to modify internal pieces of
list structure conveniently, and thus provides an alternative to
the tedious Pretty-Print, TECO, and LOAD scenario in debugging,
when it is essential to be able to insert and remove BREAKs easi-
ly. ED110 is esentially a civilized way of organizing the use of
RPLACA and RPLACD
This particular editor was inspired by Ben Wegbreit, and several
of the major design decisions were made with his guidance. This
documentation describes how I hope ED110 to perform, but I make
the usual disclaimer about possible bugs.
ED110 is written in LISP, and uses standard syntax for command
input. Thus, the full power of the interpreter is always availa-
ble for programmed editing, temporary storage, etc. The ED110
commands are LISP functions with short print strings, primarily
for convenience during type-in. To avoid name conflicts with
user's names, the other ED110 symbols are atoms whose print
strings begin with a "*". The user is cautioned to avoid rebin-
ding the ED110 command names, and to generally eschew the use of
symbols begining with *.
To gain the benefits of easy functional composition, and of a
clear convention, all ED110 functions are LAMBDAs and hence take
their arguments EVALed. The user is, of course, invited to de-
fine his own NLAMBDA version of any of the commands, if he
desires the extra convenience.
For the purposes of ED110, always think of NIL as spelled "()"
rathen than "NIL", when it occurs as an element of some list.
The conditions where this distinction is important are noted in
the following discussions.
The ED110 functions are written to tolerate the presence of non-
null, non-atomic CDRs in the buffer, even though many of the
AUXFNS are not that polite. Howeverr, there are no commands pro-
vided for manipulating them. Such facilities could easily be
added.
ED110 will also tolerate a buffer which contains dotted pairs
with several fathers, i.e., buffers which include list structure
sharing. It does insist, however, that the buffer be non-
circular.
-2-
DEFINIONS
At any point in time, ED110 is editing a particular piece of list
structure, called the BUFFER. An ENTRY of the buffer is either
any element of the buffer, or any element of any element of the
bufffer, etc; i.e., it is the data pointed to by the CAR of some
dotted pair in the buffer. A SUBLIST of the buffer is either the
entire bufffer, or a non-atomic entry of the buffer, or a null
entry of the buffer; equivalently, it is the list structure asso-
ciated with the print string between any two matching parenteses;
recall that NIL is spelled "()". A CHUNK of the buffer is any
string of zero or more elements of some sublist of the buffer.
The site of active editing in the buffer is called the POINTER,
and can be located between any two adjacent elements of any sub-
list, or before the first element of any sublist, or after the
last element of any sublist, or in the middle of a null sublist,
i.e. between the "(" and ")" of NIL. Equivalently, the pointer
can be located between any two adjacent lexemes in the print
string of the buffer. When the buffer is typed out, an asterix
is inserted at the position of the pointer, to make locating the
pointer easier. For example,
(A B (C ((D) * E)) F)
would be the result of typing out a buffer which contained the
list:
(A B (C ((D)E)) F),
when the pointer was located between the (D) and E.
The CURRENT LIST is the smallest sublist of the buffer which con-
tains the pointer. For instance, in the above example, the
current list is ((D) E).
The Sharing Guarantee
The editing functions are implemented destructively in ED110.
(Convenient facilities are provided for copying when desirable.)
In addition, any insertions or deletions at the beginning of the
buffer are performed so that the root dotted pair of the initial
buffer will be the root dotted pair of the result. Hence, if
there are multiple pointers to a particular list, which is the
present ED110 buffer, the editing of that list changes it from
everyone's point of view. In more sophisticated language, the
ED110 buffer is an R-value, not an L-value.
This guarantee generates several important issues of a fairly
technical nature, which are discussed below:
The Atomic Buffer Issue
For convenience, ED110 allows the contents of the buffer to tem-
porarily, but never permanently, degenerate to an atom, usually
-3-
NIL. In view of the sharing guarantee, this degeneration, is, of
course, "impossible"; i.e., it cannot be actually implemented
with reasonable cost. Hence, the editor merely simulates the
condition of an atomic buffer during type-out commands, selection
commands, etc. A delete command which would resullt in an atomic
buffer merely places the editor in this simulating state, and is
performed as if the buffer really had been atomic.
Thus, the buffer never degenerates to an atom. However, it will
behave as if atomic; only external pointers to the buffer will
notice the difference, and they will see the buffer's last non-
atomic contents. Therefore: the above Sharing Guarantee holds
only between two points where the buffer is non-atomic. In par-
ticular, it is impossible to change a non-null buffer to NIL, or
vice versa, using ED110 commands.
The Sharing Algorithms
Consider first the issue of inserting a list into the current
list at the location of the pointer. Note that, if the pointer
is not at the beginning of the buffer, i.e, immediatly after the
first "(", it is possible to effect this insertion by CONC'ing
the insertion with the rest of the current list, and then
RPLAC'ing a pointer to the root of the insertion into the pre-
ceding dotted pair, in the appropriate half. This is the algor-
ithm used by ED110, and the behavior in this case will be taken
as the standard for other, more questionable cases.
If the pointer is located at the beginning of the buffer,
however, it is necessary, in keeping with the Sharing Guarantee,
to interchange the roles of the root dotted pair of the insertion
and the root dotted pair of the initial buffer, and perform CONC.
If the insertion and the initial buffer do not share some of the
same dotted pairs, the above method produces a standard result,
and is used in ED110. However, if there is sharing going on,
funny things can happen.
For example, consider the implementation of the comands (B)(I
(XA)). If the above algorithm were applied, an unnecessary and
non-standard circularity would result, due to the fact that the
CAR of the insertion EQ's the initial buffer's root. When the
roles of the roots are switched, this sharing becomes circulari-
ty. To allow commands of the above ilk to operate successfully,
ED110 climbs the insertion and handles specially all pointers to
the root dotted pair of the initial buffer. This is expensive,
but convenient, and consistent. Thus, the above commands will
produce a standard result, a buffer with sharing, but without
circularity.
Of course, the situation has a certain symmetry. A non-standard
result result would also insue if the initial buffer contained a
pointer to the root dotted pair of the insertion. However, ED110
makes no special effort to handle this case, since both the
-4-
standard and the non-standard outcomes are circular, and hence,
illegal in ED110. If desirable, this type of special handling
could be easily added. It was left out only to avoid the resul-
ting inefficiency.
Note that precisely similar issues arise in the implementation of
the (XD) command; they are handled in the analogous fashion.
The Commands of ED110
Throughout the following command descriptions, small letters
standing alone will be used to reepresent arbitrary lists
EVALing to an object on the given kind. The letters i, j, and k
will stand for integers; s represents an arbitrary list; m
represents an atom.
Note also that all atom names are shown as upper case for lexo-
graphical clarity. However, like all system defined L110 atoms,
they are lower case (normal type in mode).
Examples of commands' actions will be given in the following
format: each will take two successive lines. The first line's
left half will be the state of the buffer before the command's
execution; its right half will be the text of the command. The
next line will contain the resulting state of the buffer and the
value returned by the command in its left and right parts,
respectively.
-5-
The Pointer Transportation Commands
(W l), Walk
This command walks the pointer past k elements of the
current list, i.e., makes the pointer follow k CDRs. If
k<0, the pointer is walked backwards. (W 0) is a no-op. An
attempt to walk the pointer off an end of the current list
walks the pointer as far as possible in the desired direc-
tion. Thus, (W 1000000000) will always bring the pointer to
the end of the current list.
Walk returns as value the number of successful steps walked.
If the argument is defaulted or non-numeric, (W 1) is as-
sumed.
Examples:
(A * (A B) C D) (W 2)
(A (A B) C * D) 2
(A B C * D) (W -5)
(* A B C D) -3
(J k), Jump
This command jumps the pointer down k levels of list struc-
ture, i.e., makes the pointer follow k CARs. In the prin-
tout, this corresponds too moving the pointer past k left
parentheses. Note that the pointer must be positioned im-
mediatly before a left paren in order to make a (J 1) com-
mand successful.
If k<0, the pointer is pulled out of levels of list struc-
ture. If, at any point in this process, the pointer is not
immediatly after a left paren, it is walked backwards in the
current list until it is. (J 0) is a no-op. Attempts to
jump to far into or out of the buffer will jump the pointer
as far as possible. Thus, a (J -10000000) will bring the
pointer back to the beginning of the buffer.
Jump returns as value the number of successful levels jum-
ped. If the argument is defaulted or non-numeric, (J 1) is
assumed.
Examples:
(A ((A B (* (((C D) E)))))) (J 2)
(A ((A B (((* (C D) E)))))) 2
(A * ((A B ((C D) E)))) (J 3)
(A ((* A B ((C D) E))) 2
(((((B) C) ((B (* (E F))))))) (J -4)
((* (A ((B) C)((D ((E F))))))) -4
-6-
(C k), Climb
This is a convenience command which, by calling walk and
jump, moves the pointer over k lexemes of the print string
of the buffer. If k>0, the climbing is to the right; if
k<0, to the left. (C 0) is a no-op. An attempt to climb of
the far end of the buffer will move the pointer as far as
possible in the desired direction.
Climb returns as value the number of lexemes successfully
climbed. If k is defaulted or non-numeric, (C 1) is as-
sumed.
Remember that, for the purposes of ED110, NIL is always
spelled "()". Hence, a NIL in the buffer counts as two lex-
emes to be climbed over, not one.
Examples:
((A Nil (((C D) E * F)))) (C -3)
((A NIL (((C * D) E F)))) -3
((* A NIL ((C D) E))) (C 2)
((A (*) ((C D) E))) 2
((A (*) ((C D) E))) (C -5)
(* (A NIL ((C D) E))) -3
-7-
The Insertion Commands
(I s) Insert
This command takes one argument, an arbitrary piece of list
structure, and inserts it as an element into the current
list, at the position of the pointer; the pointer is left
after the inserted element. Insert uses one new dotted pair
to hold the extra element of the current list. The value
returned is always T.
Example:
(A B (C) * D E) (I '(F H))
(A B (C) (F H) * D E) T
(IC s) Insert Copied
(LAMBDA(s)(I (COPY s]
(IB s) Insert leaving Pointer Before
This command performs the same function as Insert, but
leaves the pointer before the new element of the current
list. It returns T.
Examples:
(* A B C) (IB 's)
(* S A B C) T
(IBC s) Insert leaving pointer before, Copied.
(LAMBDA (s)(IB (COPY s]
(IL s) Insert List
This command takes one argument, an arbitrary list, s, and
inserts the elements of s into the current list at the posi-
tion of the pointer. It leaves the pointer after the newly
inserted elements. The current list's length will increase
by exactly the (LENGTH s). No new Dotted Pairs are used;
the value returned is T.
Note the difference between (I s) and (IL s) as follows:
Examples:
(A B (C) * D E) (IL '(F H))
(A B (C) F H * E) T
(ILC s) Insert List Copied
-8-
(ILB s) Insert List leaving pointer Before
(ILBC s) Insert List leaving pointer Before, Copied.
-9-
Selection, Deletion, and Typing Commands.
The ED110 commands which deal with chunks of the buffer take
three integer arguments, (? i j k); the chunk of the list
structure refered to is that from where the pointer would be
after execution of a (J k)(W i), to where it would be after
the execution of a (J k)(W j). If these arguments are om-
mitted or non-numeric, they are defaulted to i=1, j=0, and
k=0. For examples of the use of this argument structure,
which might seem obscure, but is, in fact, very convenient,
see the following paragraph.
(X i j k) X-select
This command takes the three chunk-selecting arguments, and
returns as value the selected chunk. The top level dotted
pairs in the returned value are all new, since the selected
chunk is not necessarily a complete sublist of the buffer.
The X-select command neither modifies the buffer nor moves
the pointer.
Examples:
(A B C (D E) * F G) (X)
(A B C (D E) * F G) (F)
(A B C (D E) * F G) (X 2)
(A B C (D E) * F G) (F G)
(A B C (D E) * F G) (X -2)
(A B C (D E) * F G) (C (D E))
(A B C (D E) * F G) (X -1 5)
(A B C (D E) * F G) ((D E) F G)
(A B C (D E) * F G) (X -17 -2)
(A B C (D E) * F G) (A B)
(A (* (B C D) E (F)) G) (X 0 2 1)
(A (* (B C D) E (F)) G) (B C)
(A (* (B C D) E (F)) G) (X 0 -3 -1)
(A (* (B C D) E (F)) G) (A)
-10-
(XC i j k) X-select, Copied
(LAMBDA(i j k)(COPY(X i j k]
(XA) X-select All
This command takes no arguments, and returns as value the
present contents of the buffer.
(XAC) X-select All, Copied
(T i j k) Type
This command takes the three chunk-selecting arguments, and
types out the selected chunk of the buffer using PPL, a
pretty-printing routine described below. The output goes to
POPORT. If the selected chunk contains the present position
of the pointer, it prints the present value of the atom
*EPTR at that place in the type-out. *EDTR is initially set
to "*". Type never modifies the buffer, or moves the
pointer; it returns the value T.
Example:
(A (B * C) D) (T -1 1 -1)
(A (B * C) D) "(A (B*C))";T
(A B C D E * F G) (T 1)
(A B C D E * F G) "(* F)";T
(A B C D E * F G) (T -2 -3)
(A B C D E * F G) "(C)"; T
(TA) Type All
This command takes no arguments, and types the contents of
the buffer, with the pointer indicated as in Type. The buf-
fer contents and pointer position are unchanged; the value
returned is T
(D i j k) Delete
This command takes the three chunk-selecting arguments, and
deletes the selected chunk of the buffer, leaving the poin-
ter where the chunk used to be. (See the note on the Atom-
ic Buffer Issue, page 4).
Examples:
-11-
(A B (* C D E ) F (G)) H) (D 2)
(A B (* (G)) H) T
(A B (* (C D E) F (G)) H) (D 0 1 -1)
(A B * H) T
(A B (* (C D E) F (G)) H) (D -2 2 1)
(A B ((* E) F (G)) H) T
(DA) Delete All
This command deletes the entire buffer in the nse described
on page 4, and returns T.
(XD i j k) X-select and Delete
This command takes the three chunk-selecting arguments, and
deletes the selected chunk from the buffer, leaving the
pointer where the chunk used to be. It returns the deleted
chunk as a value. No new dtprs are used.
Examples:
(A (B) C * D) (XD -2 2)
(A *) ((B) C D)
(A * (B) C D) (XD 0 1 1)
(A (*) C D) (B)
(XDC i j k) X-select and Delete Copied
(LAMBDA(i j k)(COPY(XD i j k]
(XDA) X-select and Delete All
(XDAC) X-select and Delete All Copied
-12-
Pattern-Matching and Search Commands
The pattern-matching commands are predicates which examine
the list structure of the buffer immediatelyy to the right
of the pointer, and test if it matches the supplied pattern,
s. The "matching" is in the sense of a special version of
EQUAL, discussed below. These commands do not move the
pointer, or alter the buffer.
(V s) equiValent to entry
This command examines the element of the current list im-
mediately after the pointer, and tests if it matches s. If
so, T is returned; else, NIL. If the pointer is immediately
before a ")", it returns NIL.
Examples:
(A B * (C D) E F) (V '(C D))
(A B * (C D) E F) T
(A B * (C) D) (V 'C)
(A B * (C) D) NIL
(VF s) equiValent to chunk, First
This command examines the next (LENGTH s) elements of the
current list, and tests if they match the elements of s. It
also insists that the pointer be located at the beginning of
the current list, i.e., that the matched chunk be an initial
segment of the current list.
Note that (Vf NIL) is a predicate which returns T iff the
pointer is immediately after a left paren.
Examples:
(* A B C D) (VF '(A B))
(* A B C D) T
(A B * C D) (VF '(C D))
(A B * C D) NIL
(VL s) equiValent to chunk, Last
This command examines the next (LENGTH s) elements of the
current list, and tests if they match the elements of s. It
also insists that the last element of the current list be
the one to atch the last element of s, i.e., that the
matched chunk be the terminal segment of the current list.
Note that (VL NIL) is a predicate which tests if the
pointer is immediatelyy before a right paren.
Example:
-13-
(A B * C D) (VL '(C))
(A B * C D) NIL
(A B * C D) (VL '(C D))
(A B * C D) T
(VM s) equiValent to chunk, Middle
This command looks at the next (LENGTH s) elements of the
current list, and tests if they match the elements of s. It
makes no extra demands, and thus will match a chunk in any
location in a sublist.
Note that (VM NIL) always returns T.
The matching routine used by these commands does a prefix-
walk-order climb over the nodes of the pattern and the buf-
fer, as does EQUAL. However, in order to facilitate more
sophisticated pattern-replacement, the routine checks any
atomic element of the pattern, to see if it is a member of
the top-level list *DUMMIES. If so, it APPLY*s that atom to
the corresponding structure in the buffer, and returns the
result of this function call. Hence, arbitrary new dummies
can be added. For example, after
(SETQ *DUMMIES (CONS 'ZORT *DUMMIES)) and
(DEF ZORT (LAMBDA(L)(ATOM L]
are executed, (V 'ZORT) will return T iff the entry fol-
lowing the pointer is atomic. Similarly, a (S 'zORT) will
leave the pointer after the next atom in the print string of
the buffer (see S below).
It is often desirable to allow different calls on such dum-
mies as functions to interact. For example consider the
case of
(SETQ *DUMMIES (CONS 'SAME *DUMMIES))
(DEF SAME
(LAMBDA(L)
(COND(SAME (EQ L (CAR SAME))
(T (SETQ SAME (CONS L NIL)) T))))
(VM '(SAME SAME)),
which will test if the next two elements of the current list
are identical. Note however, that some method of flushing
the effects of old calls on these functions is necessary
between succesive calls on the V routine. This is provided
by the function,*FLUSH, of no arguments, which is initially
defined as a no-op. It is called immediately before any
check for a match, and should be changed to a routine to
accomplish this reinitialization. In the above example, the
proper code is
(Def *FLUSH (LAMBDA()(SETQ SAME NIL.
The search commands also obey the *FLUSH convention; they
scan the buffer in left-to-right or right-to-left print
order, checking for matches to a supplied pattern, and
-14-
positioning the pointer accordingly.
(S s k) Search for entry
If k>0 this command begins searching for a match to s in the
sense of (V s) at the present position of the pointer. It
climbs to the right, and positions the pointer after the
k'th match for s, if such exists. If so, it returns T. If
not, it returns NIL, and leaves the pointer at the beginning
of the buffer.
If k<0, this command begins by doing a (C -1). It then
begins looking for matches of s in the sense of (V s), and
positions the pointer after the -k'th match, if such exists,
returning T. Else, it returns NIL, and leaves the pointer
at the beginning of the buffer.
If k=0, the command is a no-op.
Note that this command only searches for entries of the buf-
fer which match; in particular, it does not check the whole
buffer against the supplied pattern.
Examples:
(A * B D D) (S 'C)
(A B C * D) T
(A * B C D) (S 'A)
(* A B C D) NIL
(A (B C D) E *) (S 'B -1)
(A (B * C D) E) T
(* A B) (S '(A B))
(* A B) NIL
(SB s k) Search for entry, leaving pointer Before
This command finds the same match as the above, but leaves
the pointer immediately before it, in each case.
(SF s k) Search for chunk First
This command behaves like S, but looks for matches in the
sense of (VF s). The pointer is left after the last element
of the final matching chunk.
-15-
(SFB s k) Search for chunk First, leaving pointer Before
(SL s k) Search for chunk Last
This command behaves like the above S, except that the
matching is done in the sense of (VL s). The pointer is left
after the last element of the final matching chunk.
(SLB s k) Search for chunk Last, leaving pointer Before
(SM s k) Search for chunk middle
This command behaves like S, except that the matching is
done in the sense of (VM s). The pointer is left after the
last element of the final matching chunk.
(SMB s k) Search for chunk Middle, leaving pointer Before.
-16-
Initialization Commands
These commands initialise the editor by setting the con-
tents of the buffer. After initialization, the pointer is
always put at the beginning of the buffer, i.e., before its
first dotted pair. Note that, due to the Sharing Guarantee,
ED110 does not involve an "edit mode", and thus, no termina-
tion of an editing job is necessary unless the user desires
to free the ED110 buffer for garbage collection, or to use
the editor in some other buffer.
The later commands in this group deal only with the issue of
generating backup copies of functions being edited, in case
of editing disasters. They allow the user to choose whether
to edit the active or reserve copy of the function defini-
tion. The first demands more care in some special cases,
but allows the user easier testing of the edited version.
(E s) Edit This command initializes ED110 to the list structure
s. If s is not a dotted pair, Edit breaks; the value retur-
ned is T.
(EC s) Edit Copied
(LAMBDA(s)(E (COPY s]
(E N) Edit Nothing
This command takes no arguments, and initializes the editor
for creation of a new piece of list structuure. The buffer
will appear to be (*) after the execution of this command.
(EN) is equivalent to (E (CONS))(DA).
(ENC) Edit Nothing Copied
This command is equivalent to EN, and is included for sym-
metry.
(EF m) Edit Function
This command takes one atomic argument, i.e., one argument
which much eval to an atom, and initializes ED110 to the
present function definition definition of that atom, if it
exists. Otherwise, it prepares for the creation of a new
function binding, by performing the equivalent of (E
(CONS)(PUTD m (XA))(DA). The value returned is m; if the
function binding is binary#code, EF breaks.
(EFC) Edit Function Copied
-17-
This command takes one atomic argument, and returns it. It
initializes the editor to a copy of the present function
binding of m. If there is no such binding, it is equivalent
to (EN). If the function binding is binary#code, EFC
breaks.
(GR m) Generate Reserve
This command takes one atomic argument, and returns it. It
PUTs the present function binding of m on the property list
of m under the indicator 'RESERVE. If no such binding ex-
ists, GR breaks.
(GRC m) Generate Reserve Copied
Places a copy of the function binding under the indicator
'RESERVE on m's property list.
(RR m) Repace Reserve
This command takes one atomic argument, and returns it. If
no reserve copy of m exists on m's property list, RR breaks.
Otherwise, it changes m's function binding to be that reser-
ve copy.
(RRC m) Replace Reserve Copied
This command takes one atomic argument, and returns it. If
no reserve copy of m exists on m's property list, RRC
breaks. Otherwise, it changes m's function definition to be
a copy of that reserve copy.
(ER m) Edit Reserve
This command takes one atomic argument, and returns it. If
no reserve copy of m exists, ER breaks. Otherwise, it ini-
tializes the editor to that reserve copy.
(ERC m) Edit Reserve Copied
Thus, the command sequence (EF (GRC m)) generates a copy of
the present definition of m, and initializes the editor to
the active definition. An editing disaster could then be
remedied by a (RRC m).
If the user desired to edit the non-active version of the
-18-
function, he should instead use the sequence (ER (GRC m)):
the disaster recovery is then to repeat the above. However,
at the conclusion of the edit, the user must (RR m) to in-
stall the edited reserve copy as the active version of the
function.
-19-
State-Handling Commands
The state of ED110 is merely the present buffer and the
present position of the pointer within the buffer. Although
the values of several top-level atoms, such as *EDTR and
*DUMMIES, affect the actions of the editor, they are not
includedd in the state descriptors handled by the following
commands.
(Y) copY
This command alters the state of the editor so that it is at
precisely the same point in editing a copy of the original
buffer. Y returns T.
(YS s)copY State
This command takes one argument,and editor state descriptor,
and constructs a descriptor for the state that the editor
would be in after a (rS s)(Y). This new state descriptor is
the returned value. The state of the editor is not affec-
ted.
(GS) Generate State
This command takes no arguments, and returns as value an
editor state descriptor for the present state of the editor.
(GSC)Generate State Copied
(LAMBDA()(YS (GS]
(RS s) Replace State
This command takes one argument, an editor state descriptor,
and restores the editor to be in that state. RS returns T.
If the argument is not in proper form, RS breaks.
(RSC s) Replace State Copied
This comand takes one argument, and editor state descriptor,
and performs a (RS s)(Y). The argument descriptor is unaf-
fected, and the editor assumes the condition of editing a
copy of s's buffer, with the pointer in the corresponding
place.
-20-
Parenthesis-Handling Commands
(P i j k) Parenthesize
This command takes the three chunk-selecting arguments, and
inserts parens around the specified chunk. One new dotted
pair is used. The pointer is left after the newly inserted
right paren. P returns T.
(PB i j k) Parenthesize, leaving pointer Before.
(PA) Parenthesize All
This command takes no arguments, and inserts parentheses
around the entire buffer. The pointer is left after the new
right paren; T is returned.
(PAB) Parenthesize All, leaving pointer Before
(K) Kill Parenthesize
If the pointer is positioned immediately before a left
paren, (K) deletes that paren and its matching right, and
leaves the pointer where the right paren was. If so, the
value returned is T. Otherwise, (k) does nothing and re-
turns NIL.
(KB) Kill parentheses, leaving pointer before.
(M x y) Move
This command is a nice adjusting command for the many oc-
casions where things that are typed in end up in the wrong
place. It works as follows:
Package up the lexemes between where the pointer is now, and
where it would be after a (C y). Consider this new item as
a super-pointer, and walk it past x elements of the
remaining structure. Then, leave the real pointer on the
same side of the super-pointer as it was at the beginning.
If either argument is omitted or non-numeric, it is defaul-
ted to 1. If either argument is 0, the command is a no-op.
The value returned is always T. Note that the super pointer
can contain parentheses as well as atoms.
-21-
Examples:
(A (B C *) D E) (M)
(A (B C D *) E) T
(A B ((* C D ))) (M 1 -1)
(A B (C (* D ))) T
(A B (C (* D))) (M -5 -3)
((C (* A B D))) T
-22-
Pretty-Printing Commands
(PPL s) Pretty Print List
This takes one argument, and calls on PP's subroutines to
print it to POPORT nicely formated. The argument is taken
EVALED. The value of PPL is NIl.
(PPV x) Pretty Print Value
This is a NLAMBDA, which does the same thing that PP does,
except for top-level bindings. If x is atomic, it is
evaluated to produce a list of atoms; otherwise, x is used
directly as the list of atoms. The values of these atoms
are pretty-printed to POPORT in the format:
(SETQ <atom> (QUOTE <value>))
(PPF in out funlist vallist) Pretty-Print File
This command is a LAMBDA analogous to ECL's UNPARSF. The
file in is opened for input, and the file out is opened for
output. Then, forms are successively parsed from in, and
pretty-printed to out. If in is NIL, no input file is used.
If out is NIL, output is to the teletype.
The third argument is an update list for functional bin-
dings. While in is being read, any statement of the form
(DEF <atom> <>) for any atom in the list funlist, will
result in the present function binding to that atom being
pretty printed to out, rather that the binding given in the
input file. If any elements of funlist are not DEFed in in,
they are pretty-printed to out at the end of the file.
The fourth argument, vallist, is an equivalent update list
for top-level bindings of atoms, with the same conventions
vis-a-vis SETQs in the input file.
-23-
Convenience Commands
(Z) Z-see
This command is short for (T 0 1 -1), and thus types the
current list (surrounded with one extra pair of parens).
(A p q) Alter
This command, similar to a TECO FS, does a (S p); if this
fails, it returns NIL. If the search succeds, (D -1)(I q)
is performed, and T is returned.
(AA p q) Alter All
Like a TECO <FSp$q$;>$$. The command loops to perform the
above alteration throughout the buffer. The pointer is left
at the beginning of the buffer, and T is returned.
(L p l) Loop
This command is for use in programmed editing with ED110.
The first argument is interpreted as and editing program,
the second as a list of function names. L iterates through
l, initializing the editor to edit these functions, and then
EVALing p.
-24-